/****************************************************
 * File: gtkhelp.c
 *
 * Author: Fred Engler
 *
 * Description: Handles the online FPC help.
 ****************************************************/

#include "gtktrack.h"
#include "gtkhelp.h"
#include <stdio.h>

#define FSCANLINE(x) fscanf(fp,"%1023[^\n]\n",x)
#define GETCURDIR (strcmp(dirName,"") ? dirName : ".")
#define LINE_WIDTH 365   /*Width of line in pixels*/

extern FILE *graphQueryOpen();

/* cari - 10.5.2 - need to close from fpp2 so removed static */
GtkWidget *help_window=NULL;    /* The window to display help in*/
static GtkWidget *help_vbox;           /* The vbox to put inside the help_window*/
static GtkWidget *print_help_window=NULL;  /* Small dialog window for printing help*/
static char print_command[MAXPATHLEN] = "lpr";  /* The print command*/

/*                     DEF: get_buf_mem
 * Memory allocation function for the buffer that stores
 * all the text for the selected section*/
void
get_buf_mem(char **buf, int num_buf, int *max_buf){
   /*Allocate memory if we need it.*/
   if (num_buf+1025 >= *max_buf) {
      if (*max_buf==0){
          *max_buf=5000;
          *buf = (char *) calloc(sizeof(char),*max_buf);
          NOMEM2(*buf,"buf");
      }
      else {
          *max_buf+=2500;
          *buf = (char *) realloc(*buf, sizeof(char)*(*max_buf));
          NOMEM2(*buf,"buf");
      }
   }
}

/*                     DEF: get_help_text_from_file
 * Put the text after heading into buffer and return it.
 * Help file path is set by user or from environment variable*/
char *
get_help_text_from_file(char *filename, char *heading){
  char oneline[1024];
  char str[1024];
  char *buf = NULL;
  int num_buf=0;
  int max_buf=0;
  FILE *fp;
  int in_section=FALSE;
  int found_section=FALSE;
  char dirName2[MAXPATHLEN+1];
  char filName[MAXPATHLEN+1];
  
  if(!strcmp(filename, " ")){
    /* Environment variable FPCHELP was not set*/
    strcpy(dirName2, dirName);
    filName[0]='\0';
    fp = graphQueryOpen(dirName2,filName,"htm","r","Please locate FPC helpdoc file");
    if(fp==NULL) return NULL;
    else sprintf(filename, "%s/%s",dirName2, filName);

  }
  else{
    if((fp=fopen(filename, "r"))==NULL) goto read_error;
  }
  while(!feof(fp)){
    if(FSCANLINE(oneline)<1) goto read_error;
    if(sscanf(oneline, "<a name=%[^>\n]", str)==1){
      if(!strcmp(str, heading)){
        /* We found the heading*/
        found_section=TRUE;
        in_section=TRUE;
      }
      else in_section=FALSE;
    }
    else if(in_section){
      get_buf_mem(&buf, num_buf, &max_buf);
      sprintf(buf, "%s %s",buf, oneline);
      num_buf+=strlen(oneline)+1;
    }
    else if(found_section & !in_section){
      fclose(fp);
      return buf;
    }
  }
  if(found_section){
    fclose(fp);
    return buf;
  }

  g_warning("No help found for heading: %s\n", heading);
  fclose(fp);
  return NULL;

read_error:
  g_warning("Error occured while reading help file: %s\n", filename);
  // fclose(fp); cari 5.4.6 - crashes if doesn't exist
  return NULL;
}

/*                     DEF: write_to_help_text_box
 * Parse the help text 'str' and write to GTK window.
 * 'str' is in a simplified HTML format: <h1>-<h4> and <br>
 * is allowed. */
void
write_to_help_text_box(GtkTextView *text_box, char *str){
  char line[1024];
  int length, heading=0, in_tag=FALSE, in_end_tag=FALSE;
  int i,j=0;
  GtkTextBuffer* buffer;
  GtkTextTag* tag1, *tag2, *tag3, *tag4;
  GtkTextIter it1, it2;
  buffer = gtk_text_view_get_buffer (text_box);

  tag1 = gtk_text_buffer_create_tag (buffer, 0,"foreground", "violet", NULL);  
  tag2 = gtk_text_buffer_create_tag (buffer, 0,"foreground", "blue", NULL);  
  tag3 = gtk_text_buffer_create_tag (buffer, 0,"foreground", "#228B22", NULL);  
  tag4 = gtk_text_buffer_create_tag (buffer, 0,"foreground", "gray", NULL);  


  length = strlen(str);
  for(i=0;i<length;i++){
    if(str[i]=='<'){
      if((str[i+1]=='p') && (str[i+2]=='r') && (str[i+3]=='e')){
        i+=4;
        continue;
      }
      else if((str[i+1]=='/') && (str[i+2]=='p') && (str[i+3]=='r') && (str[i+4]=='e')){
        i+=5;
        continue;
      }
      in_tag=TRUE;
      if((j!=0) && !heading){
	/*flush line*/
	line[j]='\0';
	strcat(line, "\n");
    gtk_text_buffer_insert_at_cursor(buffer,line,-1); 

	j=0;
	while(line[j] == ' ') j++;  
	if(j>0) line[--j]='\0';
        // doesn't work with two consecutive <br>'s
      }
    }
    else if(str[i]=='>' && in_tag){
      in_tag=FALSE;
      if(in_end_tag){
        if(tolower(str[i-2])=='h'){  /*End heading; print line*/
	  line[j] = '\0';
	  strcat(line, "\n");
	  if(heading == 1)
      {            
	  /* heading 1 title*/
	    gtk_text_buffer_insert_at_cursor(buffer,line,-1); 
        gtk_text_buffer_get_iter_at_offset(buffer,&it1,gtk_text_buffer_get_char_count(buffer)-strlen(line));
        gtk_text_buffer_get_end_iter(buffer,&it2);
        gtk_text_buffer_apply_tag (buffer, tag1, &it1, &it2);
            strcpy(line,"  ");
            j=2;
	  }
	  else if(heading == 2)
      {
	  /* heading 2 title*/
	    gtk_text_buffer_insert_at_cursor(buffer,line,-1); 
        gtk_text_buffer_get_iter_at_offset(buffer,&it1,gtk_text_buffer_get_char_count(buffer)-strlen(line));
        gtk_text_buffer_get_end_iter(buffer,&it2);
        gtk_text_buffer_apply_tag (buffer, tag2, &it1, &it2);

            strcpy(line,"    ");
            j=4;
	  }
	  else if(heading == 3)
      {
	  /* heading 3 title*/
	     gtk_text_buffer_insert_at_cursor(buffer,line,-1); 
        gtk_text_buffer_get_iter_at_offset(buffer,&it1,gtk_text_buffer_get_char_count(buffer)-strlen(line));
        gtk_text_buffer_get_end_iter(buffer,&it2);
        gtk_text_buffer_apply_tag (buffer, tag3, &it1, &it2);

            strcpy(line,"      ");
            j=6;
	  }
	  else if(heading == 4)
     {
	  /* heading 4 title*/
	     gtk_text_buffer_insert_at_cursor(buffer,line,-1); 
        gtk_text_buffer_get_iter_at_offset(buffer,&it1,gtk_text_buffer_get_char_count(buffer)-strlen(line));
        gtk_text_buffer_get_end_iter(buffer,&it2);
        gtk_text_buffer_apply_tag (buffer, tag4, &it1, &it2);

            strcpy(line,"        ");
            j=8;
          }
          heading=0;
        }
        in_end_tag=FALSE;
      }
    }
    else if(in_tag && !in_end_tag && (tolower(str[i]) == 'h')){
      switch(str[++i]){
        case '1':
          heading=1;
          strcpy(line,"");
          j=0;
          break;
        case '2':
          heading=2;
          strcpy(line,"  ");
          j=2;
          break;
        case '3':
          heading=3;
          strcpy(line,"    ");
          j=4;
          break;
        case '4':
          heading=4;
          strcpy(line,"      ");
          j=6;
          break;
        default:
          heading=0;
      }
      gtk_text_buffer_insert_at_cursor(buffer,"\n",-1); 
    }
    else if(in_tag && (str[i]=='/')){
      in_end_tag=TRUE;
    }
    else if(!in_tag){
      line[j++]=str[i];
      line[j]='\0';
      if(gdk_string_width(gtk_style_get_font(GTK_WIDGET(text_box)->style), line) > LINE_WIDTH){
        /* Backtrack to last word boundary*/
        while((line[j] != ' ') && (j>0)){ j--; i--;}
        line[j]='\0';
        strcat(line, "\n");
	    gtk_text_buffer_insert_at_cursor(buffer,line,-1);
        j=0;
        while(line[j] == ' ') j++;  /* Leave indent space*/
        if(j>0) line[--j]='\0';
      }
    }
  }
  if(j!=0){      // for last line only
    /*flush line*/
    line[j]='\0';     /* signifies the beginning of the line */
    strcat(line, "\n");
    gtk_text_buffer_insert_at_cursor(buffer,line,-1);
    j=0;
  }
}

/*                     DEF: do_print_help
 * Writes the contents of the text box widget to 
 * a postscript file, and executes print command.
 * Removes postscript file once print job sent.*/
static void
do_print_help(GtkWidget *widget){
  char c, line[1024];
  gchar* text;
  int i, j=0, nchars;
  GtkTextBuffer *buffer;
  GtkTextIter it1;
  GtkTextIter it2;
  int page_top=747;
  int page_bottom=36;
  int left_mar=36;
  int next_line;
  FILE *fp;
  char file_path[MAXPATHLEN+1];
  char cmd_str[MAXPATHLEN];

  sprintf(file_path, "%s/.helptmp.ps", GETCURDIR);

  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
  
  if((fp=fopen(file_path, "w"))==NULL){
    g_warning("Unable to open file for printing");
    return;
  }

  nchars=gtk_text_buffer_get_char_count(buffer);

  fprintf(fp,"%%!\n/Courier findfont\n9 scalefont\nsetfont\n\n");

  fprintf(fp,"newpath\n");
  next_line=page_top;

  gtk_text_buffer_get_bounds(buffer,&it1,&it2);
  text = gtk_text_iter_get_slice(&it1,&it2);

  for(i=0;i<nchars;i++){
    c=text[i];
    if(c=='\n'){
      line[j]='\0';
      fprintf(fp,"%d %d moveto\n",left_mar,next_line);
      fprintf(fp,"(%s) show\n",line);
      j=0;
      next_line -= 11;
      if(next_line<page_bottom){
	fprintf(fp,"showpage\n\n");
	next_line=page_top;
      }
    }
    else{
      if((c=='(') || (c==')'))
        line[j++]='\\';
      line[j++]=c;
    }
  }
  if(next_line!=page_top) fprintf(fp,"showpage\n\n");
  fclose(fp);

  sprintf(cmd_str, "%s %s\n", print_command, file_path);
  printf("printing... ");
  fflush(stdout);
  system(cmd_str);
  sprintf(cmd_str, "rm -f %s\n", file_path);
  system(cmd_str);
  printf("done.\n");
  if(print_help_window != NULL) gtk_widget_destroy(print_help_window);
}

/*                     DEF: entry1_callback
 * Print command entry callback*/
static void
entry1_callback(GtkWidget *widget, gpointer data){
  strcpy(print_command, gtk_entry_get_text(GTK_ENTRY(widget)));
}

/*                     DEF: print_cancel_button_callback
 * Cancel printing.*/
static void
print_cancel_button_callback(GtkWidget *widget, gpointer data){
  print_help_window=NULL;
}

/*                     DEF: print_help
 * Simple GTK dialog box for printing Help window contents*/
static void
print_help(GtkWidget *widget){
  GtkWidget *hbox;
  GtkWidget *vbox;
  GtkWidget *label;
  GtkWidget *entry1;
  GtkWidget *cancel_button;
  GtkWidget *print_button;

  if(print_help_window != NULL){
    gdk_window_raise(print_help_window->window);
    return;
  }

  print_help_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_container_set_border_width (GTK_CONTAINER (print_help_window), 5);
  gtk_window_set_title (GTK_WINDOW (print_help_window), "Print Help");
  gtk_window_set_policy (GTK_WINDOW (print_help_window), FALSE, TRUE, FALSE);
  gtk_signal_connect (GTK_OBJECT (print_help_window), "destroy",
		      GTK_SIGNAL_FUNC (print_cancel_button_callback), NULL);

  vbox=gtk_vbox_new(FALSE, 5);
  gtk_container_add (GTK_CONTAINER (print_help_window), vbox);

  hbox=gtk_hbox_new(FALSE,5);
  label = gtk_label_new("Print command:");
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
  entry1 = gtk_entry_new_with_max_length(MAXPATHLEN);
  gtk_entry_set_text(GTK_ENTRY(entry1), print_command);
  gtk_signal_connect (GTK_OBJECT (entry1), "changed",
		      GTK_SIGNAL_FUNC (entry1_callback), NULL);
  gtk_box_pack_start(GTK_BOX(hbox), entry1, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

  hbox=gtk_hbox_new(FALSE,5);
  cancel_button = gtk_button_new_with_label("Cancel");
  gtk_signal_connect_object(GTK_OBJECT(cancel_button), "clicked",
		            GTK_SIGNAL_FUNC (gtk_widget_destroy),
		            GTK_OBJECT(print_help_window));
  gtk_box_pack_start (GTK_BOX (hbox), cancel_button, TRUE, TRUE, 0);

  print_button = gtk_button_new_with_label("Print");
  gtk_signal_connect_object(GTK_OBJECT (print_button), "clicked",
		      GTK_SIGNAL_FUNC (do_print_help),
		      GTK_OBJECT(widget));
  gtk_box_pack_start (GTK_BOX (hbox), print_button, TRUE, TRUE, 0);

  gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, FALSE, 0);

  gtk_widget_show_all(print_help_window);
}

/*                     DEF: show_menu
 * For the popup menu.*/
static gint
show_menu (GtkWidget *widget, GdkEventButton *event, GtkWidget *menu)
{
  if(event->button==3){
    gtk_menu_popup(GTK_MENU (menu),NULL,NULL,NULL, NULL,
                   event->button, event->time);
    return TRUE;
  }
  return FALSE;
}

/*                     DEF: help_cancel_button_callback
 * Close help window*/
static void
help_cancel_button_callback(GtkWidget *widget, gpointer data){
  if(help_window!=NULL) gtk_widget_destroy(help_window);
  help_window=NULL;
}


/*                     DEF: show_help
 * GTK graphics stuff for displaying the help window.*/
void
show_help(char *title, char *id){
  GtkWidget *text_box;
  GtkWidget *scrolled_window;
  GtkWidget *menu;
  GtkWidget *close_item;
  GtkWidget *print_item;
  char *str;
  char *loc;

  if(help_window !=NULL){
    gtk_widget_destroy(help_window);
  }
  help_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_container_set_border_width (GTK_CONTAINER (help_window), 5);
  gtk_window_set_title (GTK_WINDOW (help_window), title);
  gtk_window_set_policy (GTK_WINDOW (help_window), FALSE, TRUE, FALSE);
  gtk_window_set_default_size (GTK_WINDOW (help_window), 400, -1);
  gtk_signal_connect (GTK_OBJECT (help_window), "destroy",
		      GTK_SIGNAL_FUNC (help_cancel_button_callback), 
		      NULL);

  text_box = gtk_text_view_new();
  gtk_text_view_set_editable(GTK_TEXT_VIEW(text_box), FALSE);
  gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_box), GTK_WRAP_NONE);
  
  menu=gtk_menu_new();
  close_item=gtk_menu_item_new_with_label("Close");
  gtk_menu_append(GTK_MENU(menu),close_item);
  gtk_signal_connect_object(GTK_OBJECT(close_item),"activate",
			    GTK_SIGNAL_FUNC(gtk_widget_destroy),
			    GTK_OBJECT(help_window));
  gtk_widget_show(close_item);

  print_item=gtk_menu_item_new_with_label("Print");
  gtk_menu_append(GTK_MENU(menu),print_item);
  gtk_signal_connect_object(GTK_OBJECT(print_item),"activate",
			    GTK_SIGNAL_FUNC(print_help),
			    GTK_OBJECT(text_box));
  gtk_widget_show(print_item);

  gtk_signal_connect(GTK_OBJECT(help_window), "button_press_event",
		     GTK_SIGNAL_FUNC(show_menu), menu);

  help_vbox=gtk_vbox_new(FALSE, 10);
  gtk_container_add (GTK_CONTAINER (help_window), help_vbox);

  scrolled_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_widget_set_usize(scrolled_window,400,400);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
                                 GTK_POLICY_AUTOMATIC,
                                 GTK_POLICY_ALWAYS);
  gtk_container_add(GTK_CONTAINER(scrolled_window), text_box);
  gtk_box_pack_start (GTK_BOX (help_vbox), scrolled_window, TRUE, TRUE, 0);

  if(!strcmp(helpfilepath, " ")){
    if((loc=getenv("FPCHELP"))!=NULL)
      sprintf(helpfilepath, "%s/%s",loc, HELPDOCNAME);
  }
  str = get_help_text_from_file(helpfilepath, id);
  if(str==NULL){gtk_widget_destroy(help_window); return;}
  write_to_help_text_box(GTK_TEXT_VIEW(text_box), str);
  g_free(str);

  gtk_widget_show_all(help_window);
}

/*                     DEF: marker_edit_help
 */
void
marker_edit_help(){
  show_help("Edit Marker Track Properties Help", "editTrackHelp");
}

/*                     DEF: clone_edit_help
 */
void
clone_edit_help(){
  show_help("Edit Clone Track Properties Help", "editTrackHelp");
}

/*                     DEF: remark_edit_help
 */
void
remark_edit_help(){
  show_help("Edit Remark Track Properties Help", "editTrackHelp");
}

/*                     DEF: anchor_edit_help
 */
void
anchor_edit_help(){
  show_help("Edit Anchor Track Properties Help", "editTrackHelp");
}

/*                     DEF: ctgdisplay_help
 */
void ctgdisplay_help(){
  show_help("Contig Display Help", "ctgDisplayHelp");
}

/*                     DEF: show_legend
 * Explanation of the colors used in the contig display.*/
void show_legend(){
  show_help("Contig Display Legend", "ctgDisplayLegend");
}

